package cheme.ProcessEditor.Policies;

import java.util.List;

import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.XYLayout;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.gef.editpolicies.NonResizableEditPolicy;
import org.eclipse.gef.editpolicies.ResizableEditPolicy;
import org.eclipse.gef.editpolicies.XYLayoutEditPolicy;
import org.eclipse.gef.requests.ChangeBoundsRequest;
import org.eclipse.gef.requests.CreateRequest;

import cheme.ProcessEditor.Parts.INonResizablePart;
import cheme.ProcessEditor.Parts.IResizeablePart;
import cheme.ProcessModel.IBoundedTranslatable;
import cheme.ProcessModel.IParent;
import cheme.ProcessModel.ITranslatable;
import cheme.ProcessModel.Cmds.AddCmd;
import cheme.ProcessModel.Cmds.ChangeBoundsCmd;
import cheme.ProcessModel.Cmds.ChangeLocationCmd;
import cheme.ProcessModel.Cmds.CreateProcessUnitCmd;
import cheme.ProcessModel.ProcessUnits.IProcessUnit;


public class ProcessModelLayoutPolicy extends XYLayoutEditPolicy
{
	public ProcessModelLayoutPolicy(XYLayout xyLayout)
	{
		setXyLayout(xyLayout);
	}
	
	protected Command createAddCommand(EditPart child, Object constraint)
	{
		return null;
	}
	
	protected Command createAddCommand(Request request, EditPart childEditPart, Object constraint)
	{
		Command cmd = null;
		
		if(childEditPart.getModel() instanceof ITranslatable)
		{
			ITranslatable childModel = (ITranslatable)childEditPart.getModel();
			Rectangle rect = (Rectangle)constraint;
			AddCmd add = new AddCmd(childModel, (IParent)getHost().getModel());
			ChangeLocationCmd changeBounds = new ChangeLocationCmd(childModel, rect.getLocation());
		
			cmd = add.chain(changeBounds);
		}		
		return cmd;
	}
	
	@Override
	protected Command getAddCommand(Request generic)
	{
		ChangeBoundsRequest request = (ChangeBoundsRequest)generic;
		List editParts = request.getEditParts();
		CompoundCommand command = new CompoundCommand();
		
		GraphicalEditPart childPart;
		Rectangle r;
		Object constraint;

		for (int i = 0; i < editParts.size(); i++)
		{
			childPart = (GraphicalEditPart)editParts.get(i);
			r = childPart.getFigure().getBounds().getCopy();
			
			//convert r to absolute from childpart figure
			childPart.getFigure().translateToAbsolute(r);
			r = request.getTransformedRectangle(r);
			
			//convert this figure to relative 
			getLayoutContainer().translateToRelative(r);
			getLayoutContainer().translateFromParent(r);
			r.translate(getLayoutOrigin().getNegated());
			constraint = getConstraintFor(r);
			command.add(createAddCommand(generic, childPart, translateToModelConstraint(constraint)));
		}
		
		return command.unwrap();
	}

	protected Command createChangeConstraintCommand(EditPart child, Object constraint)
	{
//		if(child instanceof ITerminalSourcePart || child instanceof ITerminalSinkPart)
//		{
//			return null;
//		}
			
		Command command = null;
		Object model = child.getModel();
		
		if(model instanceof IBoundedTranslatable)
		{
			command = new ChangeBoundsCmd((IBoundedTranslatable)child.getModel(), ((Rectangle)constraint));
		}
		else if(model instanceof ITranslatable)
		{
			command = new ChangeLocationCmd((ITranslatable)child.getModel(), ((Rectangle)constraint).getLocation());
		}

//		command.setModel((ITranslatable)child.getModel());
//		command.setConstraint((Rectangle)constraint);

		return command;
	}

	protected Command getCreateCommand(CreateRequest request)
	{
		if(request.getNewObject() instanceof IProcessUnit)
		{
			return createCreateProcessUnitCmd(request);
		}
		
		return null;
	}
	
	protected Command createCreateProcessUnitCmd(CreateRequest request)
	{
		CreateProcessUnitCmd command = new CreateProcessUnitCmd();
		Rectangle constraint = (Rectangle)getConstraintFor(request);
		IProcessUnit model = (IProcessUnit)request.getNewObject();
		model.setLocation(constraint.getLocation());
		
		command.setParent((IParent)getHost().getModel());
		command.setChild(model);
		
		return command;
	}
	
	@Override
	protected EditPolicy createChildEditPolicy(EditPart child)
	{
		if(child instanceof INonResizablePart)
		{
			return new NonResizableEditPolicy();
		}
		// this is added to implement Vertical resizing of the console window
		else if (child instanceof IResizeablePart) 
		{
			ResizableEditPolicy policy = new ResizableEditPolicy();
			policy.setResizeDirections(PositionConstants.NORTH); 	// | PositionConstants.SOUTH|PositionConstants.EAST | PositionConstants.WEST
			return policy;		
		}
		

		return super.createChildEditPolicy(child);
	}
}